home *** CD-ROM | disk | FTP | other *** search
Text File | 1989-04-27 | 16.8 KB | 634 lines | [TEXT/????] |
- ;;; $Header: carith.scm,v 1.5 88/09/01 22:13:23 GMT cph Exp $
- ;;;; Complex Arithmetic with Operators
-
- ;;;; This file is patched by Hal to get rid of operators, making them the
- ;;;; same as 1-argument procedures. I have done this keeping in stubs, so
- ;;;; it will be easier to change when we figure out the right thing. I have
- ;;;; NOT made the corresponding changes to GARITH.
- ;;;; I have NOT worried about conditionalizing this so that it works with
- ;;;; other than the MIT system.
-
- (if-mit
- (declare (usual-integrations = + - * /
- zero? 1+ -1+
- ;; truncate round floor ceiling
- sqrt exp log sin cos)))
-
- ;;; Requires macro file <mumble>SYN.SCM (in GENERAL)
-
- ;;; The definitions follow the order in
- ;;; Revised^3 Report on the Algorithmic Language Scheme.
-
- (if-mit
-
- (define-integrable r-complex? (access complex? system-global-environment))
- (define-integrable r-number? (access number? system-global-environment))
-
- (define-integrable r-zero? (primitive zero?))
-
- (define-integrable r-= (primitive &=))
-
- (define-integrable r-1+ (primitive 1+))
- (define-integrable r--1+ (primitive -1+))
-
- (define-integrable r-+ (primitive &+))
- (define-integrable r-- (primitive &-))
- (define-integrable r-* (primitive &*))
- (define-integrable r-/ (primitive &/))
-
- (define-integrable r-sin (primitive sin))
- (define-integrable r-cos (primitive cos))
-
- (define-integrable r-sqrt (primitive sqrt))
- (define-integrable r-exp (primitive exp))
- (define-integrable r-log (primitive log))
-
- (define r-acos (access acos system-global-environment))
- (define r-asin (access asin system-global-environment))
- (define r-atan (access atan system-global-environment))
- (define r-expt (access expt system-global-environment))
- (define r-abs (access abs system-global-environment))
-
- ) ;; End of if-mit
-
- ;;; Real primitives are inherited from underlying Scheme.
-
- (if-pcs
-
- (move-definition complex? r-complex?)
- (move-definition number? r-number?)
-
- (move-definition zero? r-zero?)
-
- (move-definition = r-=)
-
- (move-definition 1+ r-1+)
- (move-definition -1+ r--1+)
-
- (move-definition + r-+)
- (move-definition - r--)
- (move-definition * r-*)
- (move-definition / r-/)
-
- (move-definition sin r-sin)
- (move-definition cos r-cos)
- (move-definition atan r-atan)
- (move-definition acos r-acos)
- (move-definition asin r-asin)
-
- (move-definition sqrt r-sqrt)
- (move-definition exp r-exp)
- (move-definition log r-log)
- (move-definition expt r-expt)
-
- (move-definition abs r-abs)
- ) ;; End of if-pcs
-
- ;;; Operator stuff
- ;;; For this version, "operators" are 1-argument procedures
-
- ;;(define-integrable operator-type '*operator*)
-
- ;;;we keep these as stubs, just in case we want to try something else.
-
- (define-integrable &procedure->operator
- (lambda (procedure) procedure))
-
-
- (define-integrable &operator?
- (lambda (object) (procedure? object)))
-
- (define-integrable &operator->procedure
- (lambda (object) object))
-
- (define identity-operator
- (&procedure->operator (lambda (object) object)))
-
- (define (operation*operator->operator operation operator)
- (&procedure->operator
- (lambda (object)
- (operation ((&operator->procedure operator) object)))))
-
- (define (operation*constant*operator->operator operation constant operator)
- (&procedure->operator
- (lambda (object)
- (operation constant ((&operator->procedure operator) object)))))
-
- (define (operation*operator*constant->operator operation operator constant)
- (&procedure->operator
- (lambda (object)
- (operation ((&operator->procedure operator) object) constant))))
-
- (define (operation*operator*operator->operator operation operator1 operator2)
- (&procedure->operator
- (lambda (object)
- (operation ((&operator->procedure operator1) object)
- ((&operator->procedure operator2) object)))))
-
- (define (procedure->operator procedure)
- (if (procedure? procedure)
- (&procedure->operator procedure)
- (error "Illegal operator definition" procedure)))
-
- (define (operator->procedure operator)
- (if (&operator? operator)
- (&operator->procedure operator)
- (lambda (object) operator)))
-
- (define (operator-compose operator1 operator2)
- (&procedure->operator
- (lambda (object)
- ((operator->procedure operator1)
- ((operator->procedure operator2)
- object)))))
-
-
- (define (operator-value operator object)
- (if (&operator? operator)
- (with-reasonable-object object (&operator->procedure operator))
- operator))
-
- ;;;this is the advertized name, in a world without operators
-
- (define (limiting-value procedure object)
- (operator-value (procedure->operator procedure) object))
-
- (define (with-reasonable-object object procedure)
- (fluid-let ((operator-value-retry
- (call-with-current-continuation
- (lambda (k)
- (lambda ()
- (set! object (perturb-object object))
- (k k))))))
- (procedure object)))
-
- ;;; Because of the following definitions, these operators are
- ;;; restricted to numbers.
-
- (define operator-perturbation-epsilon 1e-11)
-
- (define (perturb-object object)
- (+ object operator-perturbation-epsilon))
-
-
- (define (operation*operator*object->operator operation operator object)
- (cond ((or (real? object) (&complex? object))
- (operation*operator*constant->operator operation operator object))
- ((&operator? object)
- (operation*operator*operator->operator operation operator object))
- (else
- (error "Bad number" object))))
-
- (define (operation*object*operator->operator operation object operator)
- (cond ((or (real? object) (&complex? object))
- (operation*constant*operator->operator operation object operator))
- ((&operator? object)
- (operation*operator*operator->operator operation object operator))
- (else
- (error "Bad number" object))))
-
- (if-mit
-
- (define-integrable complex-type 60) ;(microcode-type 'COMPLEX) not integrated
-
- (define-integrable (&complex? z)
- (object-type? complex-type z))
-
- (define-integrable (&complex re im)
- (system-pair-cons complex-type re im))
-
- (define-integrable &real-part system-pair-car)
-
- (define-integrable &imag-part system-pair-cdr)
-
- ) ;; End of if-mit
-
- (if-pcs
-
- (define-integrable complex-type '*rect*)
-
- (define-integrable &complex?
- (lambda (z)
- (and (pair? z) (eq? (car z) complex-type))))
-
- (define-integrable &complex
- (lambda (re im)
- (list* complex-type re im)))
-
- (define-integrable &real-part cadr)
-
- (define-integrable &imag-part cddr)
-
- ) ;; End of if-pcs
-
- ;;;; Complex number data abstraction
-
- (define (&conjugate z)
- (&complex (&real-part z)
- (r-- 0 (&imag-part z))))
-
- (define (&sqr-magnitude z)
- (define r-sqr (lambda (x) (r-* x x)))
- (r-+ (r-sqr (&real-part z))
- (r-sqr (&imag-part z))))
-
- (define (&magnitude z)
- (r-sqrt (&sqr-magnitude z)))
-
- (define (&angle z m)
- (if (r-zero? m)
- (if (fluid-bound? operator-value-retry)
- ((fluid operator-value-retry))
- (error "angle: magnitude is zero"))
- (r-atan (&imag-part z) (&real-part z))))
-
-
- ;;; Complex stuff
-
- (define (&make-rectangular re im)
- (if (r-zero? im)
- re
- (&complex re im)))
-
- (define (&make-polar r theta)
- (if (r-zero? r)
- 0
- (&make-rectangular (r-* r (r-cos theta))
- (r-* r (r-sin theta)))))
-
- (define i (&make-rectangular 0 1))
- (define -i (&make-rectangular 0 -1))
-
- ;;;; Bottom layer
-
- (define-integrable (make-binary-componentwise-operation r-opr r-opi
- operator-ok?
- accum error-string)
- (letrec ((operation
- (lambda (z1 z2)
- (cond ((real? z1)
- (cond ((real? z2) (r-opr z1 z2))
- ((&complex? z2)
- (accum (r-opr z1 (&real-part z2))
- (r-opi 0 (&imag-part z2))))
- ((and operator-ok? (&operator? z2))
- (operation*constant*operator->operator operation
- z1 z2))
- (else (error error-string z2))))
- ((&complex? z1)
- (cond ((real? z2)
- (accum (r-opr (&real-part z1) z2)
- (r-opi (&imag-part z1) 0)))
- ((&complex? z2)
- (accum (r-opr (&real-part z1) (&real-part z2))
- (r-opi (&imag-part z1) (&imag-part z2))))
- ((and operator-ok? (&operator? z2))
- (operation*constant*operator->operator operation
- z1 z2))
- (else (error error-string z2))))
- ((and operator-ok? (&operator? z1))
- (operation*operator*object->operator operation z1 z2))
- (else
- (error error-string z1))))))
- operation))
-
- (define &+
- (make-binary-componentwise-operation r-+ r-+ #t
- &make-rectangular
- "+: bad number"))
-
- (define &-
- (make-binary-componentwise-operation r-- r-- #t
- &make-rectangular
- "-: bad number"))
-
- (define &=
- (make-binary-componentwise-operation r-= r-= #f
- (lambda (p q) (and p q))
- "=: bad number"))
-
- (define (&* z1 z2)
- (cond ((real? z1)
- (cond ((real? z2) (r-* z1 z2))
- ((&complex? z2)
- (&make-rectangular (r-* z1 (&real-part z2))
- (r-* z1 (&imag-part z2))))
- ((&operator? z2)
- (operation*constant*operator->operator &* z1 z2))
- (else (error "*: bad number" z2))))
- ((&complex? z1)
- (cond ((real? z2)
- (&make-rectangular (r-* (&real-part z1) z2)
- (r-* (&imag-part z1) z2)))
- ((&complex? z2)
- (&make-rectangular
- (r-- (r-* (&real-part z1) (&real-part z2))
- (r-* (&imag-part z1) (&imag-part z2)))
- (r-+ (r-* (&real-part z1) (&imag-part z2))
- (r-* (&imag-part z1) (&real-part z2)))))
- ((&operator? z2)
- (operation*constant*operator->operator &* z1 z2))
- (else (error "*: bad number" z2))))
- ((&operator? z1)
- (operation*operator*object->operator &* z1 z2))
- (else
- (error "*: bad number" z1))))
-
- (define (square z) (&* z z))
-
- (define (&/ z1 z2)
- (cond ((real? z2)
- (/real z1 z2))
- ((&complex? z2)
- (/real (&* z1 (&conjugate z2)) (&sqr-magnitude z2)))
- ((&operator? z2)
- (operation*object*operator->operator &/ z1 z2))
- (else
- (error "/: bad number" z2))))
-
- (define (/real z x)
- (cond ((r-zero? x)
- (if (fluid-bound? operator-value-retry)
- ((fluid operator-value-retry))
- (error "/: division by zero" z x)))
- ((real? z)
- (r-/ z x))
- ((&complex? z)
- (&make-rectangular (r-/ (&real-part z) x)
- (r-/ (&imag-part z) x)))
- ((&operator? z)
- (operation*operator*constant->operator /real z x))
- (else
- (error "/: bad number" z))))
-
- ;;;; User selector, constructors, and type predicates
-
-
- (define complex?
- (lambda (z)
- (or (real? z) (&complex? z))))
-
- (define (make-rectangular x y)
- (if (and (real? x) (real? y))
- (&make-rectangular x y)
- (error "Make-rectangular: bad arguments" x y)))
-
- (define (make-polar r theta)
- (if (and (real? r) (real? theta))
- (&make-polar r theta)
- (error "Make-polar: bad arguments" r theta)))
-
- (define (real-part z)
- (cond ((real? z) z)
- ((&complex? z) (&real-part z))
- ((&operator? z) (operation*operator->operator real-part z))
- (else (error "Real-part: bad number" z))))
-
- (define (imag-part z)
- (cond ((real? z) 0)
- ((&complex? z) (&imag-part z))
- ((&operator? z) (operation*operator->operator imag-part z))
- (else (error "Imag-part: bad number" z))))
-
- (define (magnitude z)
- (cond ((real? z) (r-abs z))
- ((&complex? z) (&magnitude z))
- ((&operator? z) (operation*operator->operator magnitude z))
- (else (error "Magnitude: bad number" z))))
-
- (define-integrable abs magnitude)
-
- (define (angle z)
- (cond ((real? z) (if (negative? z) pi 0))
- ((&complex? z) (&angle z (&magnitude z)))
- ((&operator? z) (operation*operator->operator angle z))
- (else (error "Angle: bad number" z))))
-
- (define (conjugate z)
- (cond ((real? z) z)
- ((&complex? z) (&conjugate z))
- ((&operator? z) (operation*operator->operator conjugate z))
- (else (error "Conjugate: bad number" z))))
-
- ;;;; Unary arithmetic and predicates
-
- (define zero?
- (lambda (z)
- (cond ((real? z)
- (r-zero? z))
- ((&complex? z)
- (and (r-zero? (&real-part z))
- (r-zero? (&imag-part z))))
- (else
- (error "Zero?: Bad complex number" z)))))
-
- (define-integrable make-unary-componentwise-operation
- (lambda (r-op error-string)
- (letrec ((operation
- (lambda (z)
- (cond ((real? z)
- (r-op z))
- ((&complex? z)
- (&make-rectangular (r-op (&real-part z))
- (&imag-part z)))
- ((&operator? z)
- (operation*operator->operator operation z))
- (else
- (error error-string z))))))
- operation)))
-
- (define 1+
- (make-unary-componentwise-operation r-1+ "1+: bad number"))
-
- (define -1+
- (make-unary-componentwise-operation r--1+ "-1+: bad number"))
-
- ;;;; N-ary predicates
-
- ;;; Predicates are extensions of common Lisp because they can be
- ;;; given no arguments, in which case they return `#t'.
-
- (define-integrable make-pairwise-test
- (lambda (&pred)
- (lambda args
- (define (loop x y rem)
- (and (&pred x y)
- (or (null? rem)
- (loop y (car rem) (cdr rem)))))
- (or (null? args)
- (null? (cdr args))
- (loop (car args) (cadr args) (cddr args))))))
-
- (define = (make-pairwise-test &=))
-
- ;;;; N-ary arithmetic
-
- (define-integrable accumulation
- (lambda (operation identity)
- (lambda rest
- (define (loop accum rem)
- (if (null? rem)
- accum
- (loop (operation accum (car rem)) (cdr rem))))
- (cond ((null? rest) identity)
- ((null? (cdr rest)) (car rest))
- (else (operation (car rest) (loop (cadr rest) (cddr rest))))))))
-
- (define + (accumulation &+ 0))
- (define * (accumulation &* 1))
-
- (define-integrable inverse-accumulation
- (lambda (operation1 operation2 identity)
- (lambda rest
- (define (loop accum rem)
- (if (null? rem)
- accum
- (loop (operation2 accum (car rem)) (cdr rem))))
- (cond ((null? rest) identity)
- ((null? (cdr rest)) (operation1 identity (car rest)))
- ((null? (cddr rest)) (operation1 (car rest) (cadr rest)))
- (else (operation1 (car rest) (loop (cadr rest) (cddr rest))))))))
-
- (define - (inverse-accumulation &- &+ 0))
- (define / (inverse-accumulation &/ &* 1))
-
- ;;;; Transcendental functions
-
- (define (exp z)
- (cond ((real? z) (r-exp z))
- ((&complex? z)
- (&make-polar (r-exp (&real-part z)) (&imag-part z)))
- ((&operator? z)
- (operation*operator->operator exp z))
- (else (error "Exp: bad number" z))))
-
- (define (log z)
- (cond ((real? z)
- (if (negative? z)
- (&make-rectangular (error-log (r-- 0 z)) pi)
- (error-log z)))
- ((&complex? z)
- (let ((m (&magnitude z)))
- (&make-rectangular (error-log m) (&angle z m))))
- ((&operator? z)
- (operation*operator->operator log z))
- (else
- (error "log: bad number" z))))
-
- (define (error-log x)
- (if (r-zero? x)
- (if (fluid-bound? operator-value-retry)
- ((fluid operator-value-retry))
- (error "log: Log of zero"))
- (r-log x)))
-
- (define (expt z1 z2)
- (if (and (real? z1) (real? z2))
- (r-expt z1 z2)
- (exp (&* z2 (log z1)))))
-
- (define log10
- (let ((e^base (r-log 10)))
- (lambda (z)
- (/ (log z) e^base))))
-
- (define (sqrt z)
- (cond ((real? z)
- (if (negative? z)
- (&make-rectangular 0 (r-sqrt (r-- 0 z)))
- (r-sqrt z)))
- ((&complex? z)
- (let ((m (&magnitude z)))
- (&make-polar (r-sqrt m)
- (r-/ (&angle z m) 2))))
- ((&operator? z)
- (operation*operator->operator sqrt z))
- (else
- (error "sqrt: bad number" z))))
-
- (define sin
- (let ((2i (&* 2 i)))
- (lambda (z)
- (cond ((real? z) (r-sin z))
- ((&complex? z)
- (let ((iz (&* i z)))
- (&/ (&- (exp iz) (exp (&- 0 iz)))
- 2i)))
- ((&operator? z)
- (operation*operator->operator sin z))
- (else
- (error "sin: bad number" z))))))
-
- (define (cos z)
- (cond ((real? z) (r-cos z))
- ((&complex? z)
- (let ((iz (&* i z)))
- (&/ (&+ (exp iz) (exp (&- 0 iz)))
- 2)))
- ((&operator? z)
- (operation*operator->operator cos z))
- (else
- (error "cos: bad number" z))))
-
- (define (tan z)
- (cond ((real? z)
- (let ((den (r-cos z)))
- (if (r-zero? den)
- (if (fluid-bound? operator-value-retry)
- ((fluid operator-value-retry))
- (error "tan: Overflow" z))
- (r-/ (r-sin z) den))))
- ((&complex? z)
- (let* ((iz (&* i z))
- (den (&+ (exp iz) (exp (&- 0 iz)))))
- (if (zero? den)
- (if (fluid-bound? operator-value-retry)
- ((fluid operator-value-retry))
- (error "tan: Overflow" z))
- (&* -i (&/ (&- (exp iz) (exp (&- 0 iz))) den)))))
- ((&operator? z)
- (operation*operator->operator tan z))
- (else
- (error "tan: bad number" z))))
-
- (define atan
- (let ((2i (&* 2 i)))
- (lambda (y . optionals)
- (let ((x (if (not (null? optionals)) (car optionals) 1)))
- (if (and (real? y) (real? x))
- (r-atan y x)
- (let ((iy (&* i y)))
- (&/ (&- (log (&+ x iy)) (log (&- x iy))) 2i)))))))
-
- (define (acos z)
- (if (and (real? z) (<= z 1) (>= z -1))
- (r-acos z)
- (&* -i (log (&- z (&* -i (sqrt (&- 1 (&* z z)))))))))
-
- (define (asin z)
- (if (and (real? z) (<= z 1) (>= z -1))
- (r-asin z)
- (&* -i (log (&+ (&* i z) (sqrt (&- 1 (&* z z))))))))
-
- (define-integrable number? complex?)
-
- (define operator?
- (lambda (z)
- (or (number? z) (&operator? z))))
-
-
- ;;; Because there is no rationals here.
-
- (define make-rational /)
-
-
- ;;; 6.003 useful operators
-
- (define s identity-operator)
- (define t identity-operator)
-
- ;;; For electrical engineers
-
- (define j i)
- (define -j -i)
-